返回值

  一个没有声明为void的函数都必须返回一个值(然而main()是特殊的;3.2节)。与此相反,void函数就不能返回值。例如,

    int f1(){ }                // 错误❌:缺返回值
    void f2() { }              // ok

    int f3() { return 1; }     // ok
    void f4() { return 1; }    // 错误❌:在void函数里返回值

    int f5() { return; }       // 错误❌:缺返回值
    void f6() { return; }      // ok

返回值由返回语句描述。例如,

int fac(int n){ return (n > 1) ? n * fac(n - 1) : 1; }

一个调用自己的函数被称为递归的。

  函数里可以出现多个返回语句:

    int fac2(int n)
    {
        if(n > 1) return n * fac2(n - 1);
        return 1;
    }

就像参数传递的语义一样,函数返回值的语义也与初始化的语义相同,可以认为返回语句所做的就是去初始化一个具有返回类型的匿名变量。这时将对照函数的返回类型检查返回表达式的类型,并执行所有标准的或用户定义的转换。例如,

double f(){ return 1; }        // 1被隐式地转换到double(1)

每当一个函数被调用时,就会建立起它的所有参数和局部(自动)变量的一套新副本。在该函数返回后,这些存储又会被另做他用。所以,绝不能返回指向局部变量的指针,因为被指位置中内容的改变情况是无法预料的:

int* fp(){ int local = 1; /* ... */ return &local; }    // 错❌

这种错误一般没有通过引用造成的类似错误那么普遍:

int& fr(){ int local = 1; /* ... */ return local; }     // 错❌

幸运的是,编译器很容易对返回局部变量的引用提出警告。

  void函数不能返回值。当然,由于对void函数的调用不会产生任何值,所以,一个void函数可以将另一个void函数作为它的return语句的表达式。例如,

void g(int* p);
void h(int* p){ /* ... */ return g(p); }    // 可以:返回“无值”

这种返回形式有其重要性,如果要写的模板函数的返回类型是模板参数,就很可能需要用这种东西(18.4.4.2节)。

🔚